import type { ExecutorConfig } from '../../../lib/request'
import type { RequestConfig } from '../../../lib/request/service/request_handler'
import type { APIEndpoint, APIRequestOptions } from '../types'
import type {
  GreasyForkOfficialScript,
  GreasyForkOfficialScriptVersions,
  GreasyForkOfficialUser,
} from './types'
import { RequestExecutor } from '../../../lib/request'
import { logger } from '../../../types/constants'
import { GREASY_FORK_BASE_URL } from '../../../types/constants/web_link'
import { SYMBOLS } from '../../../types/interfaces'
import { API_DEFAULT_CONFIG } from '../types'
import {
  GREASY_FORK_API_ENDPOINTS,
  GreasyForkAPIEndpoint,
} from './types'

export class GreasyForkAPI {
  readonly name: string = 'GreasyForkAPI'
  static instance: GreasyForkAPI
  private readonly executor = RequestExecutor.getInstance()
  private readonly baseURL: string = GREASY_FORK_BASE_URL

  static getInstance(): GreasyForkAPI {
    if (!GreasyForkAPI.instance)
      GreasyForkAPI.instance = new GreasyForkAPI()
    return GreasyForkAPI.instance
  }

  private async request<T = any>(
    endpoint: GreasyForkAPIEndpoint,
    params: Record<string, string | number> = {},
    options: APIRequestOptions = {},
  ): Promise<T> {
    const endpointConfig = GREASY_FORK_API_ENDPOINTS[endpoint]
    if (!endpointConfig) {
      throw new Error(`不支持的 API 端点: ${endpoint}`)
    }

    // 构建 URL
    const url = this.buildURL(endpointConfig.path, params)

    // 构建执行器配置
    const executorConfig = this.buildExecutorConfig(endpointConfig, options)

    logger.debug(`[${this.name}] 开始 API 请求`, {
      endpoint,
      url,
      description: endpointConfig.description,
    })

    const result = await this.executor.executeRequest<T>(url, executorConfig)

    if (!result.success) {
      throw new Error(`${endpointConfig.description}失败: ${result.error?.message || '未知错误'}`)
    }

    logger.success(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} ${endpointConfig.description}成功`, {
      endpoint,
      duration: `${result.duration}ms`,
      cached: result.cached,
      retryCount: result.retryCount,
    })

    return result.data!
  }

  /**
   * 构建 URL
   */
  private buildURL(path: string, params: Record<string, string | number>): string {
    let url = `${this.baseURL}${path}`

    // 替换路径参数
    Object.keys(params).forEach((key) => {
      const placeholder = `{${key}}`
      if (url.includes(placeholder)) {
        url = url.replace(placeholder, String(params[key]))
      }
    })

    return url
  }

  /**
   * 构建执行器配置
   */
  private buildExecutorConfig(
    endpointConfig: APIEndpoint,
    options: APIRequestOptions,
  ): ExecutorConfig & RequestConfig {
    return {
      ...options,
      scenario: options.scenario ?? endpointConfig.defaultScenario ?? API_DEFAULT_CONFIG.defaultScenario,
      enableCache: endpointConfig.enableCache ?? API_DEFAULT_CONFIG.enableCache ?? false,
      retryCount: options.retryCount ?? endpointConfig.defaultRetryCount ?? API_DEFAULT_CONFIG.defaultRetryCount,
    }
  }

  /**
   * 获取脚本信息
   */
  async getScript<T = GreasyForkOfficialScript>(
    id: string,
    options: APIRequestOptions = {},
  ): Promise<T> {
    return this.request<T>(GreasyForkAPIEndpoint.SCRIPT, { id }, options)
  }

  /**
   * 获取脚本版本历史
   */
  async getScriptVersions<T = GreasyForkOfficialScriptVersions>(
    id: string,
    options: APIRequestOptions = {},
  ): Promise<T> {
    return this.request<T>(GreasyForkAPIEndpoint.SCRIPT_VERSIONS, { id }, options)
  }

  /**
   * 获取用户信息
   */
  async getUser<T = GreasyForkOfficialUser>(
    id: string,
    options: APIRequestOptions = {},
  ): Promise<T> {
    return this.request<T>(GreasyForkAPIEndpoint.USER, { id }, options)
  }

  /**
   * 获取用户的所有脚本
   */
  async getUserScripts<T = GreasyForkOfficialScript[]>(
    id: string,
    options: APIRequestOptions = {},
  ): Promise<T> {
    const result = await this.request<GreasyForkOfficialUser>(GreasyForkAPIEndpoint.USER_SCRIPTS, { id }, options)
    return (result.scripts || []) as T
  }
}
